package com.pt25.base.model.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;


@Slf4j
@Component
final public class WebsocketStarter {

    @Resource
    private WebsocketProperties websocketProperties;

    @Resource
    private WebsocketChannelInitializer websocketChannelInitializer;

    private EventLoopGroup mainGroup;

    private EventLoopGroup subGroup;

    @PostConstruct
    public void start() throws Exception {
        //单独线程启动netty，不然会阻塞主线程的启动
        new Thread(() -> {
            // 定义一对线程组
            // 主线程组, 用于接受客户端的连接，
            mainGroup = new NioEventLoopGroup();
            // 从线程组, 负责IO交互工作
            subGroup = new NioEventLoopGroup();
            try {
                //netty服务器的创建, 辅助工具类，用于服务器通道的一系列配置
                ServerBootstrap server = new ServerBootstrap();
                //绑定两个线程组
                server.group(mainGroup, subGroup)
                        //指定NIO的模式
                        .channel(NioServerSocketChannel.class)
                        //子处理器，用于处理workerGroup
                        .childHandler(websocketChannelInitializer);
                // 启动server，并且设置4444为启动的端口号，同时启动方式为同步
                ChannelFuture future = server.bind(websocketProperties.getPort()).sync();
                log.info("websocket start on {} port", websocketProperties.getPort());
                // 监听关闭的channel，设置位同步方式
                future.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                log.error(e.getMessage());
            } finally {
                //退出线程组
                mainGroup.shutdownGracefully();
                subGroup.shutdownGracefully();
            }
        }).start();
    }

    @PreDestroy
    private void destroy() throws InterruptedException {
        if (null != mainGroup) {
            mainGroup.shutdownGracefully().sync();
        }
        if (null != subGroup) {
            subGroup.shutdownGracefully().sync();
        }
    }

}
